﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BOSS.Domain.Security
{
    /// <summary>
    /// 特权组
    /// </summary>
    [Serializable]
    public class PrivilegeGroup
    {
        private List<Privilege> m_privileges;

        /// <summary>
        /// 获取 特权集合
        /// </summary>
        public ICollection<Privilege> Privileges
        {
            get
            {
                return this.m_privileges;
            }
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        public PrivilegeGroup()
        {
            this.m_privileges = new List<Privilege>();
        }

        /// <summary>
        /// 添加特权
        /// </summary>
        /// <param name="name"></param>
        /// <param name="permission"></param>
        public void AddPrivilege(string name, PermissionType permission)
        {
            this.m_privileges.Add(new Privilege(name, permission));
        }

        /// <summary>
        /// 添加特权
        /// </summary>
        /// <param name="privilege"></param>
        public void AddPrivilege(Privilege privilege)
        {
            this.m_privileges.Add(privilege);
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="group"></param>
        private PrivilegeGroup(PrivilegeGroup group)
        {
            this.m_privileges = new List<Privilege>();
            foreach (Privilege privilege in group.Privileges)
            {
                this.m_privileges.Add(privilege.Clone());
            }
        }

        /// <summary>
        /// 克隆实例
        /// </summary>
        /// <returns></returns>
        internal PrivilegeGroup Clone()
        {
            return new PrivilegeGroup(this);
        }

        /// <summary>
        /// 根据合并规则对指定特权进行合并
        /// </summary>
        /// <param name="target"></param>
        internal void Merge(Privilege target)
        {
            foreach (Privilege current in this.m_privileges)
            {
                if (current.Name.Equals(target.Name, StringComparison.OrdinalIgnoreCase))
                {
                    if (target.Permission == PermissionType.INHERIT)
                    {
                        return;
                    }

                    switch (current.Permission)
                    {
                        case PermissionType.DEFAULT_ALLOW:
                            if (target.Permission != PermissionType.DEFAULT_DENY)
                            {
                                current.Permission = target.Permission;
                            }
                            break;

                        case PermissionType.DEFAULT_DENY:
                            if (target.Permission != PermissionType.DEFAULT_ALLOW)
                            {
                                current.Permission = target.Permission;
                            }
                            break;

                        case PermissionType.INHERIT:
                            current.Permission = target.Permission;
                            break;

                        case PermissionType.ALLOW:
                            if ((target.Permission == PermissionType.DENY)
                                || (target.Permission == PermissionType.ENFORCE_ALLOW)
                                || (target.Permission == PermissionType.ENFORCE_DENY))
                            {
                                current.Permission = target.Permission;
                            }
                            break;

                        case PermissionType.DENY:
                            if ((target.Permission == PermissionType.ENFORCE_ALLOW)
                                || (target.Permission == PermissionType.ENFORCE_DENY))
                            {
                                current.Permission = target.Permission;
                            }
                            break;

                        case PermissionType.ENFORCE_ALLOW:
                            if (target.Permission == PermissionType.ENFORCE_DENY)
                            {
                                current.Permission = target.Permission;
                            }
                            break;

                        case PermissionType.ENFORCE_DENY:
                            break;

                        default:
                            break;
                    }

                    return;
                }
            }

            this.Privileges.Add(target);
        }

        /// <summary>
        /// 根据合并规则对指定权限组进行合并
        /// </summary>
        /// <param name="group"></param>
        internal void Merge(PrivilegeGroup group)
        {
            foreach (Privilege privilege in group.Privileges)
            {
                this.Merge(privilege);
            }
        }

        /// <summary>
        /// 冻结权限，将缺省权限许可更新为明确的许可
        /// </summary>
        internal void Freeze()
        {
            foreach (Privilege privilege in this.m_privileges)
            {
                switch (privilege.Permission)
                {
                    case PermissionType.DEFAULT_ALLOW:
                        privilege.Permission = PermissionType.ALLOW;
                        break;

                    case PermissionType.DEFAULT_DENY:
                        privilege.Permission = PermissionType.DENY;
                        break;

                    case PermissionType.INHERIT:
                        privilege.Permission = PermissionType.DENY;
                        break;

                    case PermissionType.ALLOW:
                        break;

                    case PermissionType.DENY:
                        break;

                    case PermissionType.ENFORCE_ALLOW:
                        privilege.Permission = PermissionType.ALLOW;
                        break;

                    case PermissionType.ENFORCE_DENY:
                        privilege.Permission = PermissionType.DENY;
                        break;
                }
            }
        }

        /// <summary>
        /// 根据名字对权限列表进行排序
        /// </summary>
        private void SortByName()
        {
            this.m_privileges.Sort(delegate(Privilege lhs, Privilege rhs)
            {
                return string.Compare(lhs.Name, rhs.Name, true);
            });
        }

        /// <summary>
        /// 合并权限组
        /// </summary>
        /// <param name="groups"></param>
        /// <returns></returns>
        public static PrivilegeGroup MergeAll(IList<PrivilegeGroup> groups)
        {
            if (groups.Count == 0)
            {
                return null;
            }
            else
            {
                PrivilegeGroup group = groups[0].Clone();
                ;
                for (int i = 1; i < groups.Count; i++)
                {
                    group.Merge(groups[i]);
                }
                group.Freeze();
                group.SortByName();
                return group;
            }
        }
    }
}
